home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / pascal / pascal_t.lha / another_wirth next >
Text File  |  1993-07-28  |  67KB  |  1,843 lines

  1. From barbey@disuns2.epfl.ch Fri May 10 09:56:57 1991
  2. Received: from chx400.switch.ch by neuron.tamu.edu (AA22290); Fri, 10 May 91 09:56:14 CDT
  3. X400-Received: by mta chx400.switch.ch in /PRMD=switch/ADMD=arcom/C=CH/;
  4.                Relayed; Fri, 10 May 1991 16:56:56 +0200
  5. X400-Received: by /PRMD=SWITCH/ADMD=ARCOM/C=CH/; Relayed;
  6.                Fri, 10 May 1991 17:52:51 +0200
  7. Date: Fri, 10 May 1991 14:56:56 +0000
  8. X400-Originator: barbey@disuns2.epfl.ch
  9. X400-Mts-Identifier: [/PRMD=SWITCH/ADMD=ARCOM/C=CH/;9105101452.AA02428]
  10. X400-Content-Type: P2-1984 (2)
  11. From: barbey@disuns2.epfl.ch
  12. Message-Id: <9105101452.AA02428@disun15.disuns2.epfl.ch>
  13. To: "(Tim McGuire)" <mcguire@cs.tamu.edu>
  14. Subject: Re: Wirth's Pascal-S compiler
  15. Received: from disun15 by SIC.Epfl.CH via INTERNET ; Fri, 10 May 91 16:53:55 N
  16. Return-Path: <barbey@disuns2.epfl.ch>
  17. Status: R
  18.  
  19. In article <9104241654.AA03830@neuron> you write:
  20. > I am looking for the source for Wirth's Pascal-S compiler.  I'd like to 
  21. > give it to my compiler design students for them to play with.  I have 
  22. > the hardcopy (from Barron's PASCAL: The Language and Its Implementation)
  23. > but, lazy person that I am, I have no desire to type it in.  Does anyone
  24. > have it available, either by ftp or e-mail?   I would prefer the original
  25. > version if possible.  I hear that R.E. Berry did some modifications and
  26. > included them in his book on program translation, but I don't have it 
  27. > available.  Berry's version would be acceptable.  
  28. > I would appreciate any leads you could give me.
  29. > Thanks,
  30. > Tim McGuire
  31. > mcguire@cs.tamu.edu
  32. > -- 
  33.  
  34. You'll find enclosed the source of the original Wirth's PASCAL-S compiler.
  35.  
  36. We use it at the Swiss Institute of Technology - Lausanne (EPFL) in a
  37. Compiler Design Class. The exercise was to transform it in an Object
  38. Pascal... Email me if you need more infos (syntax, ...) on that. 
  39.  
  40. I've been told that Wirth himself still use it in Swiss Institute of Technology
  41. - Zurich for his Compoiler Design Class.
  42.  
  43.  
  44. -Stephane
  45.  
  46.  
  47. --------------------------------------------------------------------------
  48. Stephane Barbey
  49. barbey@eldi.epfl.ch
  50. barbey@disuns2.epfl.ch
  51. --------------------------------------------------------------------------
  52.  
  53. PROGRAM pascals(input,output);  
  54. (*author: n.wirth, e.t.h. ch-8092 zurich, 1.3.76*)  
  55. (* version originale utilisee au cours compilation *)
  56. LABEL 99;
  57. CONST nkw = 27;     (*no. of key words*)
  58.     alng =  12;     (*no. of significant chars in identifiers*) 
  59.     llng = 72;     (*input ,line length*)
  60.     emax = 38;     (*max exponent of real numbers*) 
  61.     emin =-38;     (*min exponent*) 
  62.     kmax =  12;     (*max no. of significant digits*)
  63.     tmax = 100;     (*size of table*)
  64.     bmax =  20;     (*size of block-table*) 
  65.     amax =  30;     (*size of array-table*) 
  66.     c2max = 20;     (*size of real constant table*) 
  67.     csmax = 30;     (*max no. of cases*)
  68.     cmax = 850;     (*size of code*)
  69.     lmax =   7;     (*maximum level*)
  70.     smax = 600;     (*size of string-table*)
  71.     ermax = 58;     (*max error no.*)
  72.     omax =  63;     (*highest order code*)  
  73.     xmax = 32767;  (* 2**15 - 1 (LN) *)
  74.     nmax = maxint;  (* 2**31 - 1 (LN) *) 
  75.     lineleng = 132; (*output line length*)  
  76.     linelimit = 200;
  77.     stacksize = 1450;
  78.  
  79. TYPE symbol = (intcon,realcon,charcon,string,
  80.                notsy,plus,minus,times,idiv,rdiv,imod,andsy,orsy,
  81.                eql,neq,gtr,geq,lss,leq, 
  82.                lparent,rparent,lbrack,rbrack,comma,semicolon,period,
  83.                colon,becomes,constsy,typesy,varsy,functionsy,
  84.                proceduresy,arraysy,recordsy,programsy,ident,
  85.                beginsy,ifsy,casesy,repeatsy,whilesy,forsy,  
  86.                endsy,elsesy,untilsy,ofsy,dosy,tosy,downtosy,thensy);
  87.  
  88.    pstatus =(run,fin,caschk,divchk,inxchk,stkchk,linchk,lngchk,redchk,  
  89.             iopr,igdm,ifof,ifuf,idof,ioerr,symberr,errcall);
  90.     index  = -xmax .. +xmax;
  91.     alfa = PACKED ARRAY [1..alng] OF char;  
  92.     object = (konstant,variable,type1,prozedure,funktion);  
  93.     types  = (notyp,ints,reals,bools,chars,arrays,records); 
  94.     symset = SET OF symbol; 
  95.     typset = SET OF types;  
  96.     item   = RECORD 
  97.                typ: types; ref: index;  
  98.              END ;  
  99.     order  = PACKED RECORD  
  100.                f: -omax..+omax; 
  101.                x: -lmax..+lmax; 
  102.                y: -1073741824..1073741823; (* (LN) *)
  103.              END ;  
  104.  
  105. VAR sy: symbol;          (*last symbol read by insymbol*)
  106.     id: alfa;            (*identifier from insymbol*)
  107.     inum: integer;       (*integer from insymbol*)  
  108.     rnum: real;          (*real number from insymbol*)  
  109.     sleng: integer;      (*string length*)  
  110.     ch: char;            (*last character read from source program*)
  111.     line: ARRAY [1..llng] OF char;  
  112.     cc: integer;         (*character counter*)  
  113.     lc: integer;         (*program location counter*)
  114.     ll: integer;         (*length of current line*) 
  115.     errs: SET OF 0..ermax;  
  116.     errpos: integer;
  117.     progname: alfa; 
  118.     iflag, oflag, skipflag: boolean;
  119.     constbegsys,typebegsys,blockbegsys,facbegsys,statbegsys: symset;
  120.     key: ARRAY [1..nkw] OF alfa;
  121.     ksy: ARRAY [1..nkw] OF symbol;  
  122.     sps: ARRAY [char] OF symbol;  (*special symbols*)
  123.  
  124.     t,a,b,sx,c1,c2: integer;  (*indices to tables*) 
  125.     stantyps: typset;
  126.     display: ARRAY [0 .. lmax] OF integer;  
  127.  
  128.     tab:     ARRAY [0 .. tmax] OF     (*identifier table*)  
  129.                PACKED RECORD
  130.                  name: alfa;  link: index;  
  131.                  obj: object; typ: types;
  132.                  ref: index;  normal: boolean;  
  133.                  lev: 0 .. lmax; adr: integer;  
  134.                END ;
  135.     atab:    ARRAY [1 .. amax] OF     (*array-table*)
  136.                PACKED RECORD
  137.                  inxtyp, eltyp: types;  
  138.                  elref, low, high, elsize, size: index; 
  139.                END ;
  140.     btab:    ARRAY [1 .. bmax] OF    (*block-table*)
  141.                PACKED RECORD
  142.                   last, lastpar, psize, vsize: index
  143.                END ;
  144.     stab:    PACKED ARRAY [0..smax] OF char;  (*string table*)  
  145.     rconst:  ARRAY [1 .. c2max] OF real;
  146.     code:    ARRAY [0 .. cmax] OF order;
  147.  
  148.     ps : pstatus;
  149.  
  150. PROCEDURE errormsg; 
  151.    VAR k: integer;  
  152.        msg: ARRAY [0..ermax] OF alfa;
  153. BEGIN
  154.   msg[ 0] := 'undef id    '; msg[ 1] := 'multi def   '; 
  155.   msg[ 2] := 'identifier  '; msg[ 3] := 'program     '; 
  156.   msg[ 4] := ')           '; msg[ 5] := ':           '; 
  157.   msg[ 6] := 'syntax      '; msg[ 7] := 'ident, var  '; 
  158.   msg[ 8] := 'of          '; msg[ 9] := '(           '; 
  159.   msg[10] := 'id, array   '; msg[11] := '[           '; 
  160.   msg[12] := ']           '; msg[13] := '..          '; 
  161.   msg[14] := ';           '; msg[15] := 'func. type  '; 
  162.   msg[16] := '=           '; msg[17] := 'boolean     '; 
  163.   msg[18] := 'convar typ  '; msg[19] := 'type        '; 
  164.   msg[20] := 'prog.param  '; msg[21] := 'too big     '; 
  165.   msg[22] := '.           '; msg[23] := 'typ (case)  '; 
  166.   msg[24] := 'character   '; msg[25] := 'const id    '; 
  167.   msg[26] := 'index type  '; msg[27] := 'indexbound  '; 
  168.   msg[28] := 'no array    '; msg[29] := 'type id     '; 
  169.   msg[30] := 'undef type  '; msg[31] := 'no record   '; 
  170.   msg[32] := 'boole type  '; msg[33] := 'arith type  '; 
  171.   msg[34] := 'integer     '; msg[35] := 'types       '; 
  172.   msg[36] := 'param type  '; msg[37] := 'variab id   '; 
  173.   msg[38] := 'string      '; msg[39] := 'no.of pars  '; 
  174.   msg[40] := 'real numbr  '; msg[41] := 'type        '; 
  175.   msg[42] := 'real type   '; msg[43] := 'integer     '; 
  176.   msg[44] := 'var, const  '; msg[45] := 'var, proc   '; 
  177.   msg[46] := 'types (:=)  '; msg[47] := 'typ (case)  '; 
  178.   msg[48] := 'type        '; msg[49] := 'store ovfl  '; 
  179.   msg[50] := 'constant    '; msg[51] := ':=          '; 
  180.   msg[52] := 'then        '; msg[53] := 'until       '; 
  181.   msg[54] := 'do          '; msg[55] := 'to downto   '; 
  182.   msg[56] := 'begin       '; msg[57] := 'end         '; 
  183.   msg[58] := 'factor      ';
  184.   k := 0; writeln; writeln(' key words');
  185.   WHILE errs <> [] DO
  186.   BEGIN WHILE NOT (k IN errs) DO k := k+1;  
  187.         writeln(k,'  ',msg[k]); errs := errs - [k]  
  188.   END
  189. END (*errormsg*) ;  
  190.  
  191. PROCEDURE endskip;  
  192. BEGIN (*underline skipped part of input*)
  193.    WHILE errpos < cc DO 
  194.       BEGIN write('-'); errpos := errpos + 1
  195.       END ; 
  196.    skipflag := false
  197. END (*endskip*) ;
  198.  
  199. PROCEDURE nextch;   (*read next character; process line end*)
  200. BEGIN IF cc = ll THEN
  201.       BEGIN IF eof(input) THEN  
  202.             BEGIN writeln;  
  203.                writeln(' program incomplete');  
  204.                errormsg; GOTO 99
  205.             END ;
  206.          IF errpos <> 0 THEN
  207.             BEGIN IF skipflag THEN endskip; 
  208.                writeln; errpos := 0 
  209.             END ;
  210.          write(lc:5, '  '); 
  211.          ll := 0; cc := 0;  
  212.          WHILE NOT eoln(input) DO
  213.             BEGIN ll := ll+1; read(ch); write(ch); line[ll] := ch
  214.             END ;
  215.          writeln; ll := ll+1; line[ll]:=' '; readln 
  216.       END ; 
  217.    cc := cc+1; ch := line[cc];  
  218. END (*nextch*) ;
  219.  
  220. PROCEDURE error(n: integer);
  221. BEGIN IF errpos = 0 THEN write(' ****');
  222.    IF cc > errpos THEN  
  223.       BEGIN write(' ': cc-errpos, '^', n:2);
  224.          errpos := cc+3; errs := errs + [n] 
  225.       END
  226. END (*error*) ; 
  227.  
  228. PROCEDURE fatal(n: integer);
  229.    VAR msg: ARRAY [1..7] OF alfa;
  230. BEGIN writeln; errormsg;
  231.    msg[ 1] := 'identifier  '; msg[ 2] := 'procedures  ';
  232.    msg[ 3] := 'reals       '; msg[ 4] := 'arrays      ';
  233.    msg[ 5] := 'levels      '; msg[ 6] := 'code        ';
  234.    msg[ 7] := 'strings     ';
  235.    writeln(' compiler table for ', msg[n], ' is too small');
  236.    GOTO 99    (* terminate compilation*)
  237. END (*fatal*) ; 
  238.  
  239. (*-----------------------------------------------------------insymbol-*)
  240. PROCEDURE insymbol;           (*reads next symbol*) 
  241.    LABEL 1,2,3; 
  242.    VAR i,j,k,e: integer;
  243.  
  244.    PROCEDURE readscale; 
  245.       VAR s, sign: integer; 
  246.    BEGIN nextch; sign := 1; s := 0; 
  247.       IF ch = '+' THEN nextch ELSE  
  248.       IF ch = '-' THEN BEGIN nextch; sign := -1 END ;
  249.       IF NOT (ch IN ['0'..'9']) THEN error(40)  
  250.       ELSE REPEAT s := 10*s + ord(ch) - ord('0'); nextch
  251.            UNTIL NOT (ch IN ['0'..'9']);
  252.       e := s*sign + e
  253.    END (*readscale*) ;  
  254.  
  255.    PROCEDURE adjustscale;
  256.       VAR s: integer; d,t: real;
  257.    BEGIN IF k+e > emax THEN error(21) ELSE  
  258.          IF k+e < emin THEN rnum := 0 ELSE  
  259.      BEGIN s := abs(e); t := 1.0; d := 10.0;
  260.        REPEAT
  261.          WHILE NOT odd(s) DO
  262.             BEGIN s := s DIV 2; d := sqr(d) 
  263.             END ;
  264.          s := s-1; t := d*t 
  265.        UNTIL s = 0; 
  266.        IF e >= 0 THEN rnum := rnum*t ELSE rnum := rnum/t
  267.      END
  268.    END (*adjustscale*) ;
  269.  
  270. BEGIN (*insymbol*)  
  271. 1: WHILE ch = ' ' DO nextch;
  272.    CASE ch OF
  273. 'a','b','c','d','e','f','g','h','i',
  274. 'j','k','l','m','n','o','p','q','r',
  275. 's','t','u','v','w','x','y','z',
  276. 'A','B','C','D','E','F','G','H','I',
  277. 'J','K','L','M','N','O','P','Q','R',
  278. 'S','T','U','V','W','X','Y','Z':
  279.    BEGIN (*identifier or wordsymbol*)  k := 0; id := '            ';
  280.       REPEAT IF k < alng THEN
  281.              BEGIN k := k+1;
  282.                IF ch IN ['A'..'Z'] THEN
  283.                  id[k]:=chr(ord(ch)+ord('a')-ord('A'))
  284.                ELSE id[k] := ch
  285.              END ;  
  286.          nextch 
  287.       UNTIL NOT (ch IN ['a'..'z','A'..'Z','0'..'9']);
  288.       i := 1; j := nkw;   (*binary search*) 
  289.       REPEAT k := (i+j) DIV 2;  
  290.          IF id <= key[k] THEN j := k-1; 
  291.          IF id >= key[k] THEN i := k+1  
  292.       UNTIL i > j;  
  293.       IF i-1 > j THEN sy := ksy[k] ELSE sy := ident 
  294.    END; 
  295. '0','1','2','3','4','5','6','7','8','9':
  296.    BEGIN (*number*) k := 0; inum := 0; sy := intcon;
  297.       REPEAT inum := inum*10 + ord(ch) - ord('0');  
  298.          k := k+1; nextch
  299.       UNTIL NOT (ch IN ['0'..'9']); 
  300.       IF (k > kmax) OR (inum > nmax) THEN
  301.         BEGIN error(21); inum := 0; k := 0  
  302.         END ;
  303.       IF ch = '.' THEN  
  304.       BEGIN nextch; 
  305.          IF ch = '.' THEN ch := ':' ELSE
  306.             BEGIN sy := realcon; rnum := inum; e := 0;  
  307.                WHILE ch IN ['0'..'9'] DO
  308.                BEGIN e := e-1;  
  309.                   rnum := 10.0*rnum + (ord(ch)-ord('0')); nextch
  310.                END ;
  311.                IF e = 0 THEN error(40); 
  312.                IF ch IN ['e','E'] THEN readscale;  
  313.                IF e <> 0 THEN adjustscale
  314.             END 
  315.       END ELSE  
  316.       IF ch IN ['e','E'] THEN
  317.       BEGIN sy := realcon; rnum := inum; e := 0;
  318.          readscale; IF e <> 0 THEN adjustscale  
  319.       END ; 
  320.    END; 
  321. ':': BEGIN nextch;  
  322.           IF ch = '=' THEN  
  323.             BEGIN sy := becomes; nextch 
  324.             END  ELSE sy := colon
  325.       END ; 
  326. '<' : BEGIN nextch; 
  327.          IF ch = '=' THEN BEGIN sy := leq; nextch END ELSE  
  328.          IF ch = '>' THEN BEGIN sy := neq; nextch END ELSE sy := lss
  329.       END ; 
  330. '>' : BEGIN nextch; 
  331.          IF ch = '=' THEN BEGIN sy := geq; nextch END ELSE sy := gtr
  332.       END ; 
  333. '.' : BEGIN nextch; 
  334.          IF ch = '.' THEN
  335.             BEGIN sy := colon; nextch
  336.             END  ELSE sy := period  
  337.       END ; 
  338. '''': BEGIN k := 0; 
  339.     2:  nextch; 
  340.         IF ch = '''' THEN
  341.           BEGIN nextch; IF ch <> '''' THEN GOTO 3
  342.           END ; 
  343.         IF sx+k = smax THEN fatal(7);
  344.         stab[sx+k] := ch; k := k+1; 
  345.         IF cc = 1 THEN  
  346.           BEGIN (*end of line*) k := 0; 
  347.           END
  348.         ELSE GOTO 2;
  349.     3:  IF k = 1 THEN
  350.            BEGIN sy := charcon; inum := ord(stab[sx])
  351.            END ELSE 
  352.         IF k = 0 THEN
  353.            BEGIN error(38); sy := charcon; inum := 0
  354.            END ELSE 
  355.            BEGIN sy := string; inum := sx; sleng := k; sx := sx+k
  356.            END  
  357.       END ; 
  358. '(' : BEGIN nextch; 
  359.          IF ch <> '*' THEN sy := lparent ELSE
  360.          BEGIN (*comment*) nextch;  
  361.             REPEAT  
  362.                WHILE ch <> '*' DO nextch;
  363.                nextch
  364.             UNTIL ch = ')'; 
  365.             nextch; GOTO 1  
  366.          END
  367.       END ; 
  368. '+', '-', '*', '/', ')', '=', ',', '[', ']', ';' :  
  369.       BEGIN sy := sps[ch]; nextch
  370.       END ; 
  371. '$', '!', '@', '\', '^', '_', '?',  '"', '&', '#',
  372. '%', '{', '}', '~', '`', '|' :  
  373.       BEGIN error(24); nextch; GOTO 1
  374.       END
  375.    END  
  376. END (*insymbol*) ;  
  377.  
  378. (*---------------------------------------------------------- enter ---*)
  379.  
  380. PROCEDURE enter(x0: alfa; x1: object;
  381.                 x2: types; x3: integer);
  382. BEGIN t := t+1;   (*enter standard identifier*) 
  383.    WITH tab[t] DO
  384.    BEGIN name := x0; link := t-1; obj := x1;
  385.       typ := x2; ref := 0; normal := true;  
  386.       lev := 0; adr := x3
  387.    END  
  388. END (*enter*) ; 
  389.  
  390. PROCEDURE enterarray(tp: types; l,h: integer);  
  391. BEGIN IF l > h THEN error(27);  
  392.    IF (abs(l)>xmax) OR (abs(h)>xmax) THEN
  393.       BEGIN error(27); l := 0; h := 0;  
  394.       END ; 
  395.    IF a = amax THEN fatal(4) ELSE
  396.       BEGIN a := a+1;
  397.         WITH atab[a] DO 
  398.             BEGIN inxtyp := tp; low := l; high := h 
  399.             END 
  400.       END
  401. END (*enterarray*) ;
  402.  
  403. PROCEDURE enterblock;
  404. BEGIN IF b = bmax THEN fatal(2) ELSE
  405.       BEGIN b := b+1; btab[b].last := 0; btab[b].lastpar := 0
  406.       END
  407. END (*enterblock*) ;
  408.  
  409. PROCEDURE enterreal(x: real);
  410. BEGIN IF c2 = c2max-1 THEN fatal(3) ELSE
  411.       BEGIN rconst[c2+1] := x; c1 := 1; 
  412.          WHILE rconst[c1] <> x DO  c1 := c1+1;  
  413.          IF c1 > c2 THEN c2 := c1
  414.       END
  415. END (*enterreal*) ; 
  416.  
  417. PROCEDURE emit(fct: integer);
  418. BEGIN IF lc = cmax THEN fatal(6);
  419.    code[lc].f := fct; lc := lc+1
  420. END (*emit*) ;  
  421.  
  422. PROCEDURE emit1(fct,b: integer);
  423. BEGIN IF lc = cmax THEN fatal(6);
  424.    WITH code[lc] DO 
  425.       BEGIN f := fct; y := b END ;  
  426.    lc := lc+1
  427. END (*emit1*) ; 
  428.  
  429. PROCEDURE emit2(fct,a,b: integer);  
  430. BEGIN IF lc = cmax THEN fatal(6);
  431.    WITH code[lc] DO 
  432.      BEGIN f := fct; x := a; y := b END ;
  433.    lc := lc+1
  434. END (*emit2*) ; 
  435.  
  436. PROCEDURE printtables;  
  437.    VAR i: integer; o: order;
  438. BEGIN
  439.  page(output);  
  440.    writeln(' identifiers          link  obj  typ  ref  nrm  lev  adr'); 
  441.    FOR i := btab[1].last +1 TO t DO 
  442.       WITH tab[i] DO
  443.       writeln(i:7,' ',name,link:5, ord(obj):5, ord(typ):5, ref:5,
  444.             ord(normal):5, lev:5, adr:5);
  445.        writeln; 
  446.    writeln(' blocks    last lpar psze vsze');
  447.    FOR i := 1 TO b DO
  448.       WITH btab[i] DO
  449.       writeln(i:5,'    ', last:5, lastpar:5, psize:5, vsize:5); 
  450.        writeln; 
  451.    writeln(' arrays    xtyp etyp eref  low high elsz size');
  452.    FOR i := 1 TO a DO
  453.       WITH atab[i] DO
  454.       writeln(i:5,'    ', ord(inxtyp):5, ord(eltyp):5,  
  455.               elref:5, low:5, high:5, elsize:5, size:5);
  456.        writeln; 
  457.    writeln(' code:');
  458.    FOR i := 0 TO lc-1 DO
  459.    BEGIN IF i MOD 5 = 0 THEN
  460.          BEGIN writeln; write(i:5)  
  461.          END ;  
  462.       o := code[i]; write(o.f:5);
  463.       IF o.f < 31 THEN  
  464.         IF o.f < 4 THEN write(o.x:2, o.y:5) 
  465.                     ELSE write(o.y:7)
  466.       ELSE write('       ');
  467.       write(',')
  468.    END ;
  469.    writeln  
  470. END (*printtables*) ;
  471.  
  472. (*-------------------------------------------------------------block--*)
  473.  
  474. PROCEDURE block(fsys: symset; isfun: boolean; level: integer);  
  475.  
  476.    TYPE conrec =
  477.       RECORD CASE tp: types OF  
  478.          ints,chars,bools: (i: integer);
  479.          reals: (r: real)
  480.       END ; 
  481.  
  482.    VAR dx: integer;    (*data allocation index*)
  483.        prt: integer;   (*t-index of this procedure*)
  484.        prb: integer;   (*b-index of this procedure*)
  485.        x: integer;  
  486.  
  487.    PROCEDURE skip(fsys: symset; n: integer);
  488.    BEGIN error(n); skipflag := true;
  489.       WHILE NOT (sy IN fsys) DO insymbol;
  490.       IF skipflag THEN endskip  
  491.    END (*skip*) ;
  492.  
  493.    PROCEDURE test(s1,s2: symset; n: integer);
  494.    BEGIN IF NOT (sy IN s1) THEN 
  495.          skip(s1+s2,n)  
  496.    END (*test*) ;
  497.  
  498.    PROCEDURE testsemicolon; 
  499.    BEGIN
  500.      IF sy = semicolon THEN insymbol ELSE
  501.      BEGIN error(14);
  502.        IF sy IN [comma,colon] THEN insymbol 
  503.      END ;  
  504.      test([ident]+blockbegsys, fsys, 6) 
  505.    END (*testsemicolon*) ;  
  506.    PROCEDURE enter(id: alfa; k: object);
  507.       VAR j,l: integer; 
  508.    BEGIN IF t = tmax THEN fatal(1) ELSE 
  509.          BEGIN tab[0].name := id;
  510.             j := btab[display[level]].last;  l := j;
  511.             WHILE tab[j].name <> id DO  j := tab[j].link;
  512.             IF j <> 0 THEN error(1) ELSE
  513.             BEGIN t := t+1; 
  514.               WITH tab[t] DO
  515.               BEGIN name := id; link := l;  
  516.                obj := k; typ := notyp; ref := 0; lev := level; adr := 0 
  517.               END ; 
  518.               btab[display[level]].last := t
  519.             END 
  520.          END
  521.    END (*enter*) ;  
  522.  
  523.    FUNCTION loc(id: alfa): integer; 
  524.       VAR i,j: integer;     (*locate id in table*)  
  525.    BEGIN i := level; tab[0].name := id;   (*sentinel*)  
  526.       REPEAT j := btab[display[i]].last;
  527.          WHILE tab[j].name <> id DO  j := tab[j].link;  
  528.          i := i-1;  
  529.       UNTIL (i<0) OR (j<>0);
  530.       IF j = 0 THEN error(0);  loc := j 
  531.    END (*loc*) ;
  532.  
  533.   PROCEDURE entervariable;  
  534.   BEGIN IF sy = ident THEN  
  535.           BEGIN enter(id,variable); insymbol
  536.           END
  537.         ELSE error(2)
  538.   END (*entervariable*) ;
  539.  
  540.    PROCEDURE constant(fsys: symset; VAR c: conrec); 
  541.      VAR x, sign: integer;  
  542.    BEGIN c.tp := notyp; c.i := 0;
  543.      test(constbegsys, fsys, 50);
  544.      IF sy IN constbegsys THEN  
  545.      BEGIN  
  546.          IF sy = charcon THEN
  547.            BEGIN c.tp := chars; c.i := inum; insymbol
  548.            END  
  549.          ELSE
  550.            BEGIN sign := 1; 
  551.              IF sy IN [plus,minus] THEN 
  552.                BEGIN IF sy = minus THEN sign := -1; 
  553.                  insymbol
  554.                END ;
  555.              IF sy = ident THEN 
  556.                BEGIN x := loc(id);  
  557.                  IF x <> 0 THEN 
  558.                    IF tab[x].obj <> konstant THEN error(25) ELSE
  559.                    BEGIN c.tp := tab[x].typ;
  560.                      IF c.tp = reals THEN c.r := sign*rconst[tab[x].adr]
  561.                                      ELSE c.i := sign*tab[x].adr
  562.                    END ;
  563.                  insymbol
  564.                END  
  565.              ELSE
  566.              IF sy = intcon THEN
  567.                BEGIN c.tp := ints; c.i := sign*inum; insymbol
  568.                END ELSE 
  569.              IF sy = realcon THEN
  570.                BEGIN c.tp := reals; c.r := sign*rnum; insymbol  
  571.                END ELSE skip(fsys,50)
  572.            END; 
  573.          test(fsys, [], 6)  
  574.        END  
  575.    END (*constant*) ;
  576.  
  577.    PROCEDURE typ(fsys: symset; VAR tp: types; VAR rf, sz: integer); 
  578.      VAR x: integer;
  579.          eltp: types; elrf: integer;
  580.          elsz, offset, t0,t1: integer;  
  581.  
  582.      PROCEDURE arraytyp(VAR aref,arsz: integer);
  583.         VAR eltp: types;
  584.            low, high: conrec;
  585.            elrf, elsz: integer; 
  586.      BEGIN constant([colon,rbrack,rparent,ofsy]+fsys, low); 
  587.         IF low.tp = reals THEN  
  588.            BEGIN error(27); low.tp := ints; low.i := 0  
  589.            END ;
  590.         IF sy = colon THEN insymbol ELSE error(13); 
  591.         constant([rbrack,comma,rparent,ofsy]+fsys, high);
  592.         IF high.tp <> low.tp THEN
  593.            BEGIN error(27); high.i := low.i 
  594.            END ;
  595.         enterarray(low.tp, low.i, high.i); aref := a;
  596.         IF sy = comma THEN  
  597.            BEGIN insymbol; eltp := arrays; arraytyp(elrf,elsz)  
  598.            END ELSE 
  599.         BEGIN
  600.            IF sy = rbrack THEN insymbol ELSE
  601.               BEGIN error(12);  
  602.                  IF sy = rparent THEN insymbol  
  603.               END ; 
  604.            IF sy = ofsy THEN insymbol ELSE error(8);
  605.            typ(fsys,eltp,elrf,elsz) 
  606.         END ;
  607.         WITH atab[aref] DO  
  608.         BEGIN arsz := (high-low+1)*elsz; size := arsz;  
  609.            eltyp := eltp; elref := elrf; elsize := elsz 
  610.         END ;
  611.      END (*arraytyp*) ; 
  612.  
  613.    BEGIN (*typ*) tp := notyp; rf := 0; sz := 0; 
  614.      test(typebegsys, fsys, 10);
  615.      IF sy IN typebegsys THEN
  616.        BEGIN
  617.          IF sy = ident THEN 
  618.          BEGIN x := loc(id);
  619.            IF x <> 0 THEN
  620.            WITH tab[x] DO
  621.              IF obj <> type1 THEN error(29) ELSE
  622.              BEGIN tp := typ; rf := ref; sz := adr; 
  623.                IF tp = notyp THEN error(30) 
  624.              END ;  
  625.            insymbol 
  626.          END ELSE
  627.          IF sy = arraysy THEN
  628.          BEGIN insymbol;
  629.              IF sy = lbrack THEN insymbol ELSE  
  630.                 BEGIN error(11);
  631.                    IF sy = lparent THEN insymbol
  632.                 END ;
  633.              tp := arrays; arraytyp(rf,sz)  
  634.          END ELSE
  635.          BEGIN (*records*) insymbol;
  636.            enterblock; tp := records; rf := b;  
  637.            IF level = lmax THEN fatal(5);
  638.            level := level+1; display[level] := b; offset := 0;  
  639.            WHILE NOT (sy IN fsys-[semicolon,comma,ident]+[endsy]) DO
  640.            BEGIN (*field section*)  
  641.              IF sy = ident THEN 
  642.              BEGIN t0 := t; entervariable;  
  643.                WHILE sy = comma DO  
  644.                  BEGIN insymbol; entervariable  
  645.                  END ;  
  646.                IF sy = colon THEN insymbol ELSE error(5);
  647.                t1 := t; 
  648.                typ(fsys+[semicolon,endsy,comma,ident],eltp,elrf,elsz);  
  649.                WHILE t0 < t1 DO 
  650.                BEGIN t0 := t0+1;
  651.                  WITH tab[t0] DO
  652.                  BEGIN typ := eltp; ref := elrf; normal := true;
  653.                    adr := offset; offset := offset + elsz
  654.                  END
  655.                END  
  656.              END ;  
  657.              IF sy <> endsy THEN
  658.              BEGIN IF sy = semicolon THEN insymbol ELSE 
  659.                    BEGIN error(14); 
  660.                      IF sy = comma THEN insymbol
  661.                    END ;
  662.                 test([ident,endsy,semicolon], fsys, 6)  
  663.              END
  664.            END ;
  665.            btab[rf].vsize := offset; sz := offset; btab[rf].psize := 0; 
  666.            insymbol; level := level-1
  667.          END ;  
  668.          test(fsys, [], 6)  
  669.        END  
  670.    END (*typ*) ;
  671.  
  672.    PROCEDURE parameterlist;     (*formal parameter list*)
  673.       VAR tp: types;
  674.           rf, sz, x, t0: integer;
  675.           valpar: boolean;  
  676.    BEGIN insymbol; tp := notyp; rf := 0; sz := 0;
  677.      test([ident, varsy], fsys+[rparent], 7);
  678.      WHILE sy IN [ident,varsy] DO
  679.        BEGIN IF sy <> varsy THEN valpar := true ELSE
  680.                BEGIN insymbol; valpar := false  
  681.                END ;
  682.          t0 := t; entervariable;
  683.          WHILE sy = comma DO
  684.             BEGIN insymbol; entervariable;  
  685.             END ;
  686.          IF sy = colon THEN 
  687.            BEGIN insymbol;  
  688.              IF sy <> ident THEN error(2) ELSE  
  689.              BEGIN x := loc(id); insymbol;  
  690.                IF x <> 0 THEN
  691.                WITH tab[x] DO
  692.                  IF obj <> type1 THEN error(29) ELSE
  693.                    BEGIN tp := typ; rf := ref;  
  694.                      IF valpar THEN sz := adr ELSE sz := 1  
  695.                    END ;
  696.              END ;  
  697.              test([semicolon,rparent], [comma,ident]+fsys, 14)  
  698.            END  
  699.          ELSE error(5); 
  700.          WHILE t0 < t DO
  701.          BEGIN t0 := t0+1;  
  702.            WITH tab[t0] DO  
  703.            BEGIN typ := tp; ref := rf;  
  704.                normal := valpar; adr := dx; lev := level;
  705.                dx := dx + sz
  706.            END  
  707.          END ;  
  708.          IF sy <> rparent THEN  
  709.          BEGIN IF sy = semicolon THEN insymbol ELSE 
  710.                BEGIN error(14); 
  711.                  IF sy = comma THEN insymbol
  712.                END ;
  713.             test([ident,varsy], [rparent]+fsys, 6)  
  714.          END
  715.        END (*while*) ;  
  716.      IF sy = rparent THEN
  717.        BEGIN insymbol;  
  718.          test([semicolon,colon], fsys, 6)
  719.        END  
  720.      ELSE error(4)  
  721.    END (*parameterlist*) ;  
  722.  
  723.    PROCEDURE constantdeclaration;
  724.      VAR c: conrec; 
  725.    BEGIN insymbol;  
  726.      test([ident], blockbegsys, 2); 
  727.      WHILE sy = ident DO
  728.        BEGIN enter(id,konstant); insymbol;  
  729.          IF sy = eql THEN insymbol ELSE 
  730.             BEGIN error(16);
  731.                IF sy = becomes THEN insymbol
  732.             END ;
  733.          constant([semicolon,comma,ident]+fsys,c);  
  734.          tab[t].typ := c.tp; tab[t].ref := 0;
  735.          IF c.tp = reals THEN
  736.            BEGIN enterreal(c.r); tab[t].adr := c1 END
  737.          ELSE tab[t].adr := c.i;
  738.          testsemicolon  
  739.        END  
  740.    END (*constantdeclaration*) ;
  741.  
  742.    PROCEDURE typedeclaration;
  743.      VAR tp: types; rf, sz, t1: integer;
  744.    BEGIN insymbol;  
  745.      test([ident], blockbegsys, 2); 
  746.      WHILE sy = ident DO
  747.        BEGIN enter(id,type1); t1 := t; insymbol;
  748.          IF sy = eql THEN insymbol ELSE 
  749.             BEGIN error(16);
  750.                IF sy = becomes THEN insymbol
  751.             END ;
  752.          typ([semicolon,comma,ident]+fsys, tp, rf, sz); 
  753.          WITH tab[t1] DO
  754.            BEGIN typ := tp; ref := rf; adr := sz
  755.            END ;
  756.          testsemicolon  
  757.        END  
  758.    END (*typedeclaration*) ;
  759.  
  760.    PROCEDURE variabledeclaration;
  761.      VAR t0, t1, rf, sz: integer;
  762.          tp: types; 
  763.    BEGIN insymbol;  
  764.      WHILE sy = ident DO
  765.      BEGIN t0 := t; entervariable;  
  766.        WHILE sy = comma DO  
  767.          BEGIN insymbol; entervariable; 
  768.          END ;  
  769.        IF sy = colon THEN insymbol ELSE error(5);
  770.        t1 := t; 
  771.        typ([semicolon,comma,ident]+fsys, tp, rf, sz);
  772.        WHILE t0 < t1 DO 
  773.        BEGIN t0 := t0+1;
  774.          WITH tab[t0] DO
  775.          BEGIN typ := tp; ref := rf;
  776.            lev := level; adr := dx; normal := true; 
  777.            dx := dx + sz
  778.          END
  779.        END ;
  780.        testsemicolon
  781.      END
  782.    END (*variabledeclaration*) ;
  783.  
  784.    PROCEDURE procdeclaration;
  785.       VAR isfun: boolean;
  786.    BEGIN isfun := sy = functionsy; insymbol;
  787.      IF sy <> ident THEN
  788.         BEGIN  error(2); id := '            '
  789.         END ;
  790.      IF isfun THEN enter(id,funktion) ELSE enter(id,prozedure); 
  791.      tab[t].normal := true; 
  792.      insymbol; block([semicolon]+fsys, isfun, level+1); 
  793.      IF sy = semicolon THEN insymbol ELSE error(14);
  794.      emit(32+ord(isfun))    (*exit*)
  795.    END (*proceduredeclaration*) ;
  796.  
  797. (*---------------------------------------------------------statement--*)
  798.    
  799.  
  800.    PROCEDURE statement(fsys: symset);
  801.       VAR i: integer; (* x: item; (LN) *) 
  802.  
  803.      PROCEDURE expression(fsys: symset; VAR x: item); forward; 
  804.  
  805.       PROCEDURE selector(fsys: symset; VAR v:item); 
  806.          VAR x: item; a,j: integer; 
  807.       BEGIN (*sy in [lparent, lbrack, period]*) 
  808.         REPEAT  
  809.           IF sy = period THEN
  810.           BEGIN insymbol;  (*field selector*)
  811.             IF sy <> ident THEN error(2) ELSE
  812.             BEGIN
  813.               IF v.typ <> records THEN error(31) ELSE
  814.               BEGIN (*search field identifier*) 
  815.                 j := btab[v.ref] .last; tab[0].name := id;  
  816.                 WHILE tab[j].name <> id DO j := tab[j].link;
  817.                 IF j = 0 THEN error(0); 
  818.                 v.typ := tab[j].typ; v.ref := tab[j].ref;
  819.                 a := tab[j].adr; IF a <> 0 THEN emit1(9,a)  
  820.               END ; 
  821.               insymbol  
  822.             END 
  823.           END ELSE  
  824.           BEGIN (*array selector*)  
  825.             IF sy <> lbrack THEN error(11); 
  826.             REPEAT insymbol;
  827.               expression(fsys+[comma,rbrack], x);
  828.               IF v.typ <> arrays THEN error(28) ELSE
  829.                 BEGIN a := v.ref;
  830.                   IF atab[a].inxtyp <> x.typ THEN error(26) ELSE
  831.                 IF atab[a].elsize = 1 THEN emit1(20,a) ELSE emit1(21,a);
  832.                   v.typ := atab[a].eltyp; v.ref := atab[a].elref
  833.                 END 
  834.             UNTIL sy <> comma;  
  835.             IF sy = rbrack THEN insymbol ELSE
  836.               BEGIN error(12); IF sy = rparent THEN insymbol
  837.               END
  838.           END
  839.         UNTIL NOT (sy IN [lbrack,lparent,period]);  
  840.         test(fsys, [], 6)
  841.       END (*selector*) ;
  842.  
  843.       PROCEDURE call(fsys: symset; i: integer); 
  844.          VAR x: item;
  845.              lastp, cp, k: integer; 
  846.       BEGIN emit1(18,i);  (*mark stack*)
  847.         lastp := btab[tab[i].ref].lastpar; cp := i; 
  848.         IF sy = lparent THEN
  849.         BEGIN (*actual parameter list*) 
  850.           REPEAT insymbol;  
  851.             IF cp >= lastp THEN error(39) ELSE  
  852.             BEGIN cp := cp+1;
  853.               IF tab[cp].normal THEN
  854.               BEGIN (*value parameter*) 
  855.                 expression(fsys+[comma,colon,rparent], x);  
  856.                 IF x.typ=tab[cp].typ THEN
  857.                   BEGIN 
  858.                     IF x.ref <> tab[cp].ref THEN error(36) ELSE 
  859.                   IF x.typ = arrays THEN emit1(22,atab[x.ref].size) ELSE
  860.                     IF x.typ = records THEN emit1(22,btab[x.ref].vsize) 
  861.                   END ELSE  
  862.                 IF (x.typ=ints) AND (tab[cp].typ=reals) THEN
  863.                    emit1(26,0) ELSE 
  864.                    IF x.typ<>notyp THEN error(36);  
  865.               END ELSE  
  866.               BEGIN (*variable parameter*)  
  867.                 IF sy <> ident THEN error(2) ELSE
  868.                 BEGIN k := loc(id); insymbol;
  869.                   IF k <> 0 THEN
  870.                   BEGIN IF tab[k].obj <> variable THEN error(37);
  871.                     x.typ := tab[k].typ; x.ref := tab[k].ref;
  872.                     IF tab[k].normal THEN emit2(0,tab[k].lev,tab[k].adr)
  873.                        ELSE emit2(1,tab[k].lev,tab[k].adr); 
  874.                     IF sy IN [lbrack,lparent,period] THEN
  875.                        selector(fsys+[comma,colon,rparent], x); 
  876.                     IF (x.typ<>tab[cp].typ) OR (x.ref<>tab[cp].ref) THEN
  877.                        error(36)
  878.                   END
  879.                 END 
  880.               END
  881.             END ;
  882.             test([comma,rparent], fsys, 6)  
  883.           UNTIL sy <> comma;
  884.           IF sy = rparent THEN insymbol ELSE error(4)
  885.         END ;
  886.         IF cp < lastp THEN error(39); (*too few actual parameters*) 
  887.         emit1(19, btab[tab[i].ref].psize-1);
  888.         IF tab[i].lev < level THEN emit2(3, tab[i].lev, level)  
  889.       END (*call*) ;
  890.  
  891.       FUNCTION resulttype(a,b: types): types;
  892.       BEGIN 
  893.         IF (a>reals) OR (b>reals) THEN  
  894.           BEGIN error(33); resulttype := notyp  
  895.           END ELSE  
  896.         IF (a=notyp) OR (b=notyp) THEN resulttype := notyp ELSE 
  897.         IF a=ints THEN  
  898.           IF b=ints THEN resulttype := ints ELSE
  899.             BEGIN resulttype := reals; emit1(26,1)  
  900.             END 
  901.         ELSE
  902.           BEGIN resulttype := reals;
  903.             IF b=ints THEN emit1(26,0)  
  904.           END
  905.       END (*resulttype*) ;  
  906.  
  907.       PROCEDURE expression; (* (LN) *) 
  908.         VAR y:item; op:symbol;  
  909.  
  910.         PROCEDURE simpleexpression(fsys:symset; VAR x:item);
  911.           VAR y:item; op:symbol;
  912.  
  913.           PROCEDURE term(fsys:symset; VAR x:item);  
  914.             VAR y:item; op:symbol; (* ts:typset; (LN) *)
  915.  
  916.             PROCEDURE factor(fsys:symset; VAR x:item);  
  917.               VAR i,f: integer; 
  918.  
  919.               PROCEDURE standfct(n: integer);
  920.                  VAR ts: typset;
  921.               BEGIN (*standard function no. n*) 
  922.                 IF sy = lparent THEN insymbol ELSE error(9);
  923.                 IF n < 17 THEN  
  924.                   BEGIN expression(fsys+[rparent],x);
  925.                     CASE n OF
  926. (*abs,sqr*)     0,2: BEGIN ts := [ints,reals]; tab[i].typ := x.typ; 
  927.                        IF x.typ = reals THEN n := n+1
  928.                      END ;  
  929. (*odd,chr*)     4,5: ts := [ints];  
  930. (*ord*)         6:   ts := [ints,bools,chars];  
  931. (*succ,pred*)   7,8: BEGIN ts := [ints,bools,chars]; tab[i].typ := x.typ
  932.                      END ;  
  933. (*round,trunc*) 9,10,11,12,13,14,15,16: 
  934. (*sin,cos,...*)      BEGIN ts := [ints,reals];  
  935.                          IF x.typ = ints THEN emit1(26,0)
  936.                      END ;  
  937.                     END ;
  938.                     IF x.typ IN ts THEN emit1(8,n) ELSE 
  939.                     IF x.typ <> notyp THEN error(48);
  940.                   END ELSE  
  941. (*eof,eoln*)      BEGIN (*n in [17,18]*)
  942.                     IF sy <> ident THEN error(2) ELSE
  943.                     IF id <> 'input       ' THEN error(0) ELSE insymbol;
  944.                     emit1(8,n); 
  945.                   END ; 
  946.                 x.typ := tab[i].typ;
  947.                 IF sy = rparent THEN insymbol ELSE error(4) 
  948.               END (*standfct*) ;
  949.  
  950.             BEGIN (*factor*) x.typ := notyp; x.ref := 0;
  951.               test(facbegsys, fsys, 58);
  952.               WHILE sy IN facbegsys DO  
  953.                 BEGIN
  954.                   IF sy = ident THEN
  955.                   BEGIN i := loc(id); insymbol; 
  956.                     WITH tab[i] DO  
  957.                     CASE obj OF 
  958.               konstant: BEGIN x.typ := typ; x.ref := 0; 
  959.                           IF x.typ = reals THEN 
  960.                             emit1(25,adr) ELSE  
  961.                             emit1(24,adr)
  962.                         END ;
  963.               variable: BEGIN x.typ := typ; x.ref := ref;
  964.                           IF sy IN [lbrack,lparent,period] THEN 
  965.                             BEGIN IF normal THEN f := 0 ELSE f := 1;
  966.                               emit2(f, lev, adr);
  967.                               selector(fsys,x); 
  968.                               IF x.typ IN stantyps THEN emit(34)
  969.                             END ELSE
  970.                             BEGIN
  971.                               IF x.typ IN stantyps THEN 
  972.                                 IF normal THEN f := 1 ELSE f := 2
  973.                               ELSE  
  974.                                 IF normal THEN f := 0 ELSE f := 1;  
  975.                               emit2(f, lev, adr)
  976.                             END 
  977.                         END ;
  978.               type1, prozedure:    error(44);
  979.               funktion :BEGIN x.typ := typ; 
  980.                           IF lev <> 0 THEN call(fsys, i)
  981.                                 ELSE standfct(adr)  
  982.                         END 
  983.                     END (*case,with*)
  984.                   END ELSE  
  985.                   IF sy IN [charcon,intcon,realcon] THEN
  986.                    BEGIN
  987.                      IF sy = realcon THEN
  988.                      BEGIN x.typ := reals; enterreal(rnum); 
  989.                        emit1(25, c1)
  990.                      END ELSE
  991.                      BEGIN IF sy = charcon THEN x.typ := chars  
  992.                                            ELSE x.typ := ints;  
  993.                        emit1(24, inum)  
  994.                      END ;  
  995.                      x.ref := 0; insymbol
  996.                    END ELSE 
  997.                   IF sy = lparent THEN  
  998.                    BEGIN insymbol; expression(fsys+[rparent], x);
  999.                      IF sy = rparent THEN insymbol ELSE error(4)
  1000.                    END ELSE 
  1001.                   IF sy = notsy THEN
  1002.                    BEGIN insymbol; factor(fsys,x);  
  1003.                      IF x.typ=bools THEN emit(35) ELSE  
  1004.                        IF x.typ<>notyp THEN error(32)
  1005.                    END ;
  1006.                   test(fsys, facbegsys, 6)  
  1007.                 END (*while*)
  1008.             END (*factor*) ;
  1009.  
  1010.           BEGIN (*term*)
  1011.             factor(fsys+[times,rdiv,idiv,imod,andsy], x);
  1012.             WHILE sy IN [times,rdiv,idiv,imod,andsy] DO 
  1013.               BEGIN op := sy; insymbol; 
  1014.                 factor(fsys+[times,rdiv,idiv,imod,andsy], y);
  1015.                 IF op = times THEN  
  1016.                 BEGIN x.typ := resulttype(x.typ, y.typ);
  1017.                   CASE x.typ OF 
  1018.                     notyp: ;
  1019.                     ints : emit(57);
  1020.                     reals: emit(60);
  1021.                   END
  1022.                 END ELSE
  1023.                 IF op = rdiv THEN
  1024.                 BEGIN
  1025.                   IF x.typ = ints THEN  
  1026.                     BEGIN emit1(26,1); x.typ := reals
  1027.                     END ;
  1028.                   IF y.typ = ints THEN  
  1029.                     BEGIN emit1(26,0); y.typ := reals
  1030.                     END ;
  1031.                   IF (x.typ=reals) AND (y.typ=reals) THEN emit(61) ELSE 
  1032.                     BEGIN IF (x.typ<>notyp) AND (y.typ<>notyp) THEN 
  1033.                             error(33);  
  1034.                           x.typ := notyp
  1035.                     END 
  1036.                 END ELSE
  1037.                 IF op = andsy THEN  
  1038.                 BEGIN IF (x.typ=bools) AND (y.typ=bools) THEN
  1039.                          emit(56) ELSE  
  1040.                       BEGIN IF (x.typ<>notyp) AND (y.typ<>notyp) THEN
  1041.                                error(32);
  1042.                          x.typ := notyp 
  1043.                       END
  1044.                 END ELSE
  1045.                 BEGIN (*op in [idiv,imod]*) 
  1046.                   IF (x.typ=ints) AND (y.typ=ints) THEN 
  1047.                     IF op=idiv THEN emit(58)
  1048.                                ELSE emit(59) ELSE
  1049.                     BEGIN IF (x.typ<>notyp) AND (y.typ<>notyp) THEN 
  1050.                              error(34); 
  1051.                           x.typ := notyp
  1052.                     END 
  1053.                 END 
  1054.               END
  1055.           END (*term*) ;
  1056.  
  1057.         BEGIN (*simpleexpression*)  
  1058.           IF sy IN [plus,minus] THEN
  1059.             BEGIN op := sy; insymbol;
  1060.               term(fsys+[plus,minus], x);
  1061.               IF x.typ > reals THEN error(33) ELSE  
  1062.                 IF op = minus THEN emit(36) 
  1063.             END ELSE
  1064.           term(fsys+[plus,minus,orsy], x);  
  1065.           WHILE sy IN [plus,minus,orsy] DO  
  1066.             BEGIN op := sy; insymbol;
  1067.                term(fsys+[plus,minus,orsy], y); 
  1068.                IF op = orsy THEN
  1069.                BEGIN
  1070.                  IF (x.typ=bools) AND (y.typ=bools) THEN emit(51) ELSE  
  1071.                    BEGIN IF (x.typ<>notyp) AND (y.typ<>notyp) THEN  
  1072.                             error(32);  
  1073.                          x.typ := notyp 
  1074.                    END  
  1075.                END ELSE 
  1076.                BEGIN x.typ := resulttype(x.typ, y.typ); 
  1077.                  CASE x.typ OF  
  1078.                    notyp: ; 
  1079.                    ints : IF op = plus THEN emit(52)
  1080.                                    ELSE emit(53);
  1081.                    reals: IF op = plus THEN emit(54)
  1082.                                    ELSE emit(55)
  1083.                  END
  1084.                END  
  1085.             END 
  1086.         END (*simpleexpression*) ;  
  1087.  
  1088.       BEGIN (*expression*)  
  1089.         simpleexpression(fsys+[eql,neq,lss,leq,gtr,geq], x);
  1090.         IF sy IN [eql,neq,lss,leq,gtr,geq] THEN 
  1091.           BEGIN op := sy; insymbol; simpleexpression(fsys, y);  
  1092.              IF (x.typ IN [notyp,ints,bools,chars]) 
  1093.                AND (x.typ = y.typ) THEN 
  1094.                CASE op OF
  1095.                  eql: emit(45); 
  1096.                  neq: emit(46); 
  1097.                  lss: emit(47); 
  1098.                  leq: emit(48); 
  1099.                  gtr: emit(49); 
  1100.                  geq: emit(50); 
  1101.                END ELSE 
  1102.              BEGIN IF x.typ = ints THEN 
  1103.                      BEGIN x.typ := reals; emit1(26,1)  
  1104.                      END ELSE
  1105.                    IF y.typ = ints THEN 
  1106.                      BEGIN y.typ := reals; emit1(26,0)  
  1107.                      END ;  
  1108.                IF (x.typ=reals) AND (y.typ=reals) THEN  
  1109.                  CASE op OF 
  1110.                    eql: emit(39);
  1111.                    neq: emit(40);
  1112.                    lss: emit(41);
  1113.                    leq: emit(42);
  1114.                    gtr: emit(43);
  1115.                    geq: emit(44);
  1116.                  END
  1117.                ELSE error(35)
  1118.              END ;  
  1119.              x.typ := bools 
  1120.           END
  1121.       END (*expression*) ;  
  1122.  
  1123.       PROCEDURE assignment(lv,ad: integer); 
  1124.          VAR x,y: item; f: integer; 
  1125.          (*tab[i].obj in [variable,prozedure]*) 
  1126.       BEGIN x.typ := tab[i].typ; x.ref := tab[i].ref;
  1127.         IF tab[i].normal THEN f := 0 ELSE f := 1;
  1128.         emit2(f, lv, ad);
  1129.         IF sy IN [lbrack,lparent,period] THEN
  1130.            selector([becomes,eql]+fsys, x); 
  1131.         IF sy = becomes THEN insymbol ELSE  
  1132.           BEGIN error(51); IF sy = eql THEN insymbol
  1133.           END ; 
  1134.         expression(fsys, y);
  1135.         IF x.typ = y.typ THEN
  1136.           IF x.typ IN stantyps THEN emit(38) ELSE
  1137.           IF x.ref <> y.ref THEN error(46) ELSE 
  1138.           IF x.typ = arrays THEN emit1(23, atab[x.ref].size)
  1139.                             ELSE emit1(23, btab[x.ref].vsize)
  1140.         ELSE
  1141.         IF (x.typ=reals) AND (y.typ=ints) THEN  
  1142.           BEGIN emit1(26,0); emit(38)
  1143.           END ELSE  
  1144.           IF (x.typ<>notyp) AND (y.typ<>notyp) THEN error(46)
  1145.       END (*assignment*) ;  
  1146.  
  1147.       PROCEDURE compoundstatement;  
  1148.       BEGIN insymbol;
  1149.         statement([semicolon,endsy]+fsys);  
  1150.         WHILE sy IN [semicolon]+statbegsys DO
  1151.         BEGIN IF sy = semicolon THEN insymbol ELSE error(14);
  1152.           statement([semicolon,endsy]+fsys) 
  1153.         END ;
  1154.         IF sy = endsy THEN insymbol ELSE error(57)  
  1155.       END (*compoundstatemenet*) ;  
  1156.  
  1157.       PROCEDURE ifstatement;
  1158.          VAR x: item; lc1,lc2: integer; 
  1159.       BEGIN insymbol;
  1160.         expression(fsys+[thensy,dosy], x);  
  1161.         IF NOT (x.typ IN [bools,notyp]) THEN error(17); 
  1162.         lc1 := lc; emit(11);  (*jmpc*)  
  1163.         IF sy = thensy THEN insymbol ELSE
  1164.           BEGIN error(52); IF sy = dosy THEN insymbol
  1165.           END ; 
  1166.         statement(fsys+[elsesy]);
  1167.         IF sy = elsesy THEN 
  1168.           BEGIN insymbol; lc2 := lc; emit(10);  
  1169.             code[lc1].y := lc; statement(fsys); code[lc2].y := lc
  1170.           END
  1171.         ELSE code[lc1].y := lc  
  1172.       END (*ifstatement*) ; 
  1173.  
  1174.       PROCEDURE casestatement;  
  1175.         VAR x: item;
  1176.             i,j,k,lc1: integer; 
  1177.             casetab: ARRAY [1..csmax] OF
  1178.                        PACKED RECORD val, lc: index END ;
  1179.             exittab: ARRAY [1..csmax] OF integer;
  1180.  
  1181.         PROCEDURE caselabel;
  1182.           VAR lab: conrec; k: integer;  
  1183.         BEGIN constant(fsys+[comma,colon], lab);
  1184.           IF lab.tp <> x.typ THEN error(47) ELSE
  1185.           IF i = csmax THEN fatal(6) ELSE
  1186.             BEGIN i := i+1; k := 0; 
  1187.               casetab[i].val := lab.i; casetab[i].lc := lc; 
  1188.               REPEAT k := k+1 UNTIL casetab[k].val = lab.i; 
  1189.               IF k < i THEN error(1);   (*multiple definition*) 
  1190.             END 
  1191.         END (*caselabel*) ; 
  1192.  
  1193.         PROCEDURE onecase;  
  1194.         BEGIN IF sy IN constbegsys THEN 
  1195.           BEGIN caselabel;  
  1196.             WHILE sy = comma DO 
  1197.               BEGIN insymbol; caselabel 
  1198.               END ; 
  1199.             IF sy = colon THEN insymbol ELSE error(5);  
  1200.             statement([semicolon,endsy]+fsys);  
  1201.             j := j+1; exittab[j] := lc; emit(10)
  1202.           END
  1203.         END (*onecase*) ;
  1204.  
  1205.       BEGIN insymbol; i := 0; j := 0;
  1206.         expression(fsys+[ofsy,comma,colon], x); 
  1207.         IF NOT (x.typ IN [ints,bools,chars,notyp]) THEN error(23);  
  1208.         lc1 := lc; emit(12);  (*jmpx*)  
  1209.         IF sy = ofsy THEN insymbol ELSE error(8);
  1210.         onecase;
  1211.         WHILE sy = semicolon DO 
  1212.           BEGIN insymbol; onecase
  1213.           END ; 
  1214.         code[lc1].y := lc;  
  1215.         FOR k := 1 TO i DO  
  1216.           BEGIN emit1(13,casetab[k].val); emit1(13,casetab[k].lc)
  1217.           END ; 
  1218.         emit1(10,0);
  1219.         FOR k := 1 TO j DO code[exittab[k]].y := lc;
  1220.         IF sy = endsy THEN insymbol ELSE error(57)  
  1221.       END (*casestatement*) ;
  1222.       PROCEDURE repeatstatement;
  1223.          VAR x: item; lc1: integer; 
  1224.       BEGIN lc1 := lc;  
  1225.         insymbol; statement([semicolon,untilsy]+fsys);  
  1226.         WHILE sy IN [semicolon]+statbegsys DO
  1227.         BEGIN IF sy = semicolon THEN insymbol ELSE error(14);
  1228.           statement([semicolon,untilsy]+fsys)
  1229.         END ;
  1230.         IF sy = untilsy THEN
  1231.           BEGIN insymbol; expression(fsys, x);  
  1232.             IF NOT (x.typ IN [bools,notyp]) THEN error(17); 
  1233.             emit1(11,lc1)
  1234.           END
  1235.         ELSE error(53)  
  1236.       END (*repeatstatement*) ; 
  1237.  
  1238.       PROCEDURE whilestatement; 
  1239.          VAR x: item; lc1,lc2: integer; 
  1240.       BEGIN insymbol; lc1 := lc;
  1241.         expression(fsys+[dosy], x); 
  1242.         IF NOT (x.typ IN [bools,notyp]) THEN error(17); 
  1243.         lc2 := lc; emit(11);
  1244.         IF sy = dosy THEN insymbol ELSE error(54);  
  1245.         statement(fsys); emit1(10,lc1); code[lc2].y := lc
  1246.       END (*whilestatement*) ;  
  1247.  
  1248.       PROCEDURE forstatement;
  1249.          VAR cvt: types; x: item;
  1250.              i,f,lc1,lc2: integer;  
  1251.       BEGIN insymbol;
  1252.         IF sy = ident THEN  
  1253.           BEGIN i := loc(id); insymbol; 
  1254.             IF i = 0 THEN cvt := ints ELSE  
  1255.             IF tab[i].obj = variable THEN
  1256.               BEGIN cvt := tab[i].typ;  
  1257.                 IF NOT tab[i].normal THEN error(37) ELSE
  1258.                   emit2(0, tab[i].lev, tab[i].adr); 
  1259.                 IF NOT (cvt IN [notyp,ints,bools,chars]) THEN error(18) 
  1260.               END ELSE  
  1261.               BEGIN error(37); cvt := ints  
  1262.               END
  1263.           END ELSE skip([becomes,tosy,downtosy,dosy]+fsys, 2);  
  1264.         IF sy = becomes THEN
  1265.           BEGIN insymbol; expression([tosy,downtosy,dosy]+fsys, x); 
  1266.             IF x.typ <> cvt THEN error(19); 
  1267.           END ELSE skip([tosy,downtosy,dosy]+fsys, 51); 
  1268.         f := 14;
  1269.         IF sy IN [tosy, downtosy] THEN  
  1270.           BEGIN IF sy = downtosy THEN f := 16;  
  1271.             insymbol; expression([dosy]+fsys, x);
  1272.             IF x.typ <> cvt THEN error(19)  
  1273.           END ELSE skip([dosy]+fsys, 55);
  1274.         lc1 := lc; emit(f); 
  1275.         IF sy = dosy THEN insymbol ELSE error(54);  
  1276.         lc2 := lc; statement(fsys); 
  1277.         emit1(f+1,lc2); code[lc1].y := lc
  1278.       END (*forstatement*) ;
  1279.  
  1280.       PROCEDURE standproc(n: integer);  
  1281.          VAR i,f: integer;  
  1282.              x,y: item; 
  1283.       BEGIN 
  1284.         CASE n OF
  1285.    1,2: BEGIN (*read*)  
  1286.           IF NOT iflag THEN 
  1287.             BEGIN error(20); iflag := true  
  1288.             END ;
  1289.           IF sy = lparent THEN  
  1290.           BEGIN 
  1291.             REPEAT insymbol;
  1292.               IF sy <> ident THEN error(2) ELSE 
  1293.               BEGIN i := loc(id); insymbol; 
  1294.                 IF i <> 0 THEN  
  1295.                 IF tab[i].obj <> variable THEN error(37) ELSE
  1296.                 BEGIN x.typ := tab[i].typ; x.ref := tab[i].ref; 
  1297.                   IF tab[i].normal THEN f := 0 ELSE f := 1; 
  1298.                   emit2(f, tab[i].lev, tab[i].adr); 
  1299.                   IF sy IN [lbrack,lparent,period] THEN 
  1300.                     selector(fsys+[comma,rparent], x);  
  1301.                   IF x.typ IN [ints,reals,chars,notyp] THEN 
  1302.                     emit1(27, ord(x.typ)) ELSE error(41)
  1303.                 END 
  1304.               END ; 
  1305.               test([comma,rparent], fsys, 6);
  1306.             UNTIL sy <> comma;  
  1307.             IF sy = rparent THEN insymbol ELSE error(4) 
  1308.           END ; 
  1309.           IF n = 2 THEN emit(62)
  1310.         END ;
  1311.    3,4: BEGIN (*write*) 
  1312.           IF sy = lparent THEN  
  1313.           BEGIN 
  1314.             REPEAT insymbol;
  1315.               IF sy = string THEN
  1316.                 BEGIN emit1(24,sleng); emit1(28,inum); insymbol 
  1317.                 END ELSE
  1318.               BEGIN expression(fsys+[comma,colon,rparent], x);  
  1319.                 IF NOT (x.typ IN stantyps) THEN error(41);  
  1320.                 IF sy = colon THEN  
  1321.                 BEGIN insymbol; 
  1322.                   expression(fsys+[comma,colon,rparent], y);
  1323.                   IF y.typ <> ints THEN error(43);  
  1324.                   IF sy = colon THEN
  1325.                   BEGIN IF x.typ <> reals THEN error(42);
  1326.                     insymbol; expression(fsys+[comma,rparent], y);  
  1327.                     IF y.typ <> ints THEN error(43);
  1328.                     emit(37)
  1329.                   END
  1330.                   ELSE emit1(30, ord(x.typ))
  1331.                 END 
  1332.                 ELSE emit1(29, ord(x.typ))  
  1333.               END
  1334.             UNTIL sy <> comma;  
  1335.             IF sy = rparent THEN insymbol ELSE error(4) 
  1336.           END ; 
  1337.           IF n = 4 THEN emit(63)
  1338.         END ;
  1339.         END (*case*)
  1340.       END (*standproc*) ;
  1341.  
  1342.     BEGIN (*statement*) 
  1343.       IF sy IN statbegsys+[ident] THEN  
  1344.           CASE sy OF
  1345.             ident:    BEGIN i := loc(id); insymbol; 
  1346.                         IF i <> 0 THEN  
  1347.                         CASE tab[i].obj OF  
  1348.                           konstant, type1: error(45);
  1349.                           variable: assignment(tab[i].lev, tab[i].adr); 
  1350.                           prozedure:
  1351.                             IF tab[i].lev <> 0 THEN call(fsys, i)
  1352.                                     ELSE standproc(tab[i].adr); 
  1353.                           funktion: 
  1354.                             IF tab[i].ref = display[level] THEN 
  1355.                               assignment(tab[i].lev+1, 0) ELSE error(45)
  1356.                         END 
  1357.                       END ; 
  1358.             beginsy:  compoundstatement;
  1359.             ifsy:     ifstatement;  
  1360.             casesy:   casestatement;
  1361.             whilesy:  whilestatement;
  1362.             repeatsy: repeatstatement;  
  1363.             forsy:    forstatement; 
  1364.           END;  
  1365.         test(fsys, [], 14)  
  1366.     END (*statement*) ; 
  1367.  
  1368. BEGIN (*block*) dx := 5; prt := t;  
  1369.   IF level > lmax THEN fatal(5);
  1370.   test([lparent,colon,semicolon], fsys, 14);
  1371.   enterblock; display[level] := b; prb := b;
  1372.   tab[prt].typ := notyp; tab[prt].ref := prb;
  1373.   IF (sy = lparent) AND (level > 1) THEN parameterlist; 
  1374.   btab[prb].lastpar := t; btab[prb].psize := dx;
  1375.   IF isfun THEN 
  1376.     IF sy = colon THEN  
  1377.     BEGIN insymbol;   (*function type*) 
  1378.       IF sy = ident THEN
  1379.       BEGIN x := loc(id); insymbol; 
  1380.         IF x <> 0 THEN  
  1381.           IF tab[x].obj <> type1 THEN error(29) ELSE
  1382.             IF tab[x].typ IN stantyps THEN tab[prt].typ := tab[x].typ
  1383.               ELSE error(15)
  1384.       END ELSE skip([semicolon]+fsys, 2)
  1385.     END ELSE error(5);  
  1386.   IF sy = semicolon THEN insymbol ELSE error(14);
  1387.   REPEAT
  1388.     IF sy = constsy THEN constantdeclaration;
  1389.     IF sy = typesy THEN typedeclaration;
  1390.     IF sy = varsy THEN variabledeclaration; 
  1391.     btab[prb].vsize := dx;  
  1392.     WHILE sy IN [proceduresy,functionsy] DO procdeclaration;
  1393.     test([beginsy], blockbegsys+statbegsys, 56) 
  1394.   UNTIL sy IN statbegsys;
  1395.   tab[prt].adr := lc;
  1396.   insymbol; statement([semicolon,endsy]+fsys);  
  1397.   WHILE sy IN [semicolon]+statbegsys DO 
  1398.     BEGIN IF sy = semicolon THEN insymbol ELSE error(14);
  1399.       statement([semicolon,endsy]+fsys) 
  1400.     END ;
  1401.   IF sy = endsy THEN insymbol ELSE error(57);
  1402.   test(fsys+[period], [], 6)
  1403. END (*block*) ; 
  1404.  
  1405. (*-------------------------------------------------------interpret---*) 
  1406.  
  1407. PROCEDURE interpret;
  1408.   (*global code, tab, btab*)
  1409.   LABEL 98;   (*trap label*)
  1410.   VAR ir: order;      (*instruction buffer*)
  1411.       pc: integer;    (*program counter*)
  1412.       t:  integer;    (*top stack index*)
  1413.       b:  integer;    (*base index*)
  1414.       lncnt, ocnt, blkcnt, chrcnt: integer;     (*counters*)
  1415.       h1,h2,h3,h4: integer; 
  1416.       fld: ARRAY [1..4] OF integer;     (*default field widths*)
  1417.  
  1418.       display: ARRAY [1..lmax] OF integer;  
  1419.       s: ARRAY [1..stacksize] OF          (*blockmark:              *)  
  1420.          RECORD CASE types OF             (*   s[b+0] = fct result  *)  
  1421.            ints:  (i: integer);           (*   s[b+1] = return adr  *)  
  1422.            reals: (r: real);              (*   s[b+2] = static link *)  
  1423.            bools: (b: boolean);           (*   s[b+3] = dynamic link*)  
  1424.            chars: (c: char)               (*   s[b+4] = table index *)  
  1425.          END ;  
  1426.  
  1427. BEGIN (*interpret*) 
  1428.   s[1].i := 0; s[2].i := 0; s[3].i := -1; s[4].i := btab[1].last;
  1429.   b := 0; display[1] := 0;  
  1430.   t := btab[2].vsize - 1; pc := tab[s[4].i].adr;
  1431.   ps := run;
  1432.   lncnt := 0; ocnt := 0; chrcnt := 0;
  1433.   fld[1] := 10; fld[2] := 22; fld[3] := 10; fld[4] := 1;
  1434.   REPEAT ir := code[pc]; pc := pc+1; ocnt := ocnt + 1;  
  1435.     CASE ir.f OF
  1436.   0: BEGIN (*load address*) t := t+1;
  1437.        IF t > stacksize THEN ps := stkchk
  1438.          ELSE s[t].i := display[ir.x] + ir.y
  1439.      END ;  
  1440.   1: BEGIN (*load value*) t := t+1; 
  1441.        IF t > stacksize THEN ps := stkchk
  1442.          ELSE s[t] := s[display[ir.x] + ir.y]
  1443.      END ;  
  1444.   2: BEGIN (*load indirect*) t := t+1;  
  1445.        IF t > stacksize THEN ps := stkchk
  1446.          ELSE s[t] := s[s[display[ir.x] + ir.y].i]  
  1447.      END ;  
  1448.   3: BEGIN (*update display*)
  1449.        h1 := ir.y; h2 := ir.x; h3 := b; 
  1450.        REPEAT display[h1] := h3; h1 := h1-1; h3 := s[h3+2].i
  1451.        UNTIL h1 = h2
  1452.      END ;  
  1453.   8: CASE ir.y OF
  1454.       0: s[t].i := abs(s[t].i); 
  1455.       1: s[t].r := abs(s[t].r); 
  1456.       2: s[t].i := sqr(s[t].i); 
  1457.       3: s[t].r := sqr(s[t].r); 
  1458.       4: s[t].b := odd(s[t].i); 
  1459.       5: BEGIN (* s[t].c := chr(s[t].i); *) 
  1460.            IF (s[t].i < 0) OR (s[t].i > 63) THEN ps := inxchk
  1461.          END ;  
  1462.       6: (* s[t].i := ord(s[t].c) *);
  1463.       7: s[t].c := succ(s[t].c);
  1464.       8: s[t].c := pred(s[t].c);
  1465.       9: s[t].i := round(s[t].r);
  1466.      10: s[t].i := trunc(s[t].r);
  1467.      11: s[t].r := sin(s[t].r); 
  1468.      12: s[t].r := cos(s[t].r); 
  1469.      13: s[t].r := exp(s[t].r); 
  1470.      14: s[t].r := ln(s[t].r);  
  1471.      15: s[t].r := sqrt(s[t].r);
  1472.      16: s[t].r := arctan(s[t].r);  
  1473.      17: BEGIN t := t+1;
  1474.            IF t > stacksize THEN ps := stkchk ELSE s[t].b := eof(input) 
  1475.          END ;  
  1476.      18: BEGIN t := t+1;
  1477.            IF t > stacksize THEN ps := stkchk ELSE s[t].b := eoln(input)
  1478.          END ;  
  1479.      END ;  
  1480.   9: s[t].i := s[t].i + ir.y;   (*offset*)  
  1481.  10: pc := ir.y;  (*jump*)  
  1482.  11: BEGIN (*conditional jump*) 
  1483.        IF NOT s[t].b THEN pc := ir.y;  t := t-1 
  1484.      END ;  
  1485.  12: BEGIN (*switch*) h1 := s[t].i; t := t-1;
  1486.        h2 := ir.y; h3 := 0; 
  1487.        REPEAT IF code[h2].f <> 13 THEN  
  1488.                 BEGIN h3 := 1; ps := caschk 
  1489.                 END ELSE
  1490.               IF code[h2].y = h1 THEN
  1491.                 BEGIN h3 := 1; pc := code[h2+1].y
  1492.                 END ELSE
  1493.               h2 := h2 + 2  
  1494.        UNTIL h3 <> 0
  1495.      END ;  
  1496.  14: BEGIN (*for1up*) h1 := s[t-1].i;
  1497.        IF h1 <= s[t].i THEN s[s[t-2].i].i := h1 ELSE
  1498.           BEGIN t := t-3; pc := ir.y
  1499.           END
  1500.      END ;  
  1501.  15: BEGIN (*for2up*) h2 := s[t-2].i; h1 := s[h2].i + 1;
  1502.        IF h1 <= s[t].i THEN 
  1503.          BEGIN s[h2].i := h1; pc := ir.y END
  1504.        ELSE t := t-3;
  1505.      END ;  
  1506.  16: BEGIN (*for1down*) h1 := s[t-1].i; 
  1507.        IF h1 >= s[t].i THEN s[s[t-2].i].i := h1 ELSE
  1508.           BEGIN pc := ir.y; t := t-3
  1509.           END
  1510.      END ;  
  1511.  17: BEGIN (*for2down*) h2 := s[t-2].i; h1 := s[h2].i - 1;  
  1512.        IF h1 >= s[t].i THEN 
  1513.          BEGIN s[h2].i := h1; pc := ir.y END
  1514.        ELSE t := t-3;
  1515.      END ;  
  1516.  18: BEGIN (*mark stack*)  h1 := btab[tab[ir.y].ref].vsize; 
  1517.        IF t+h1 > stacksize THEN ps := stkchk ELSE
  1518.          BEGIN t := t+5; s[t-1].i := h1-1; s[t].i := ir.y
  1519.          END
  1520.      END ;  
  1521.  19: BEGIN (*call*) h1 := t - ir.y;  (*h1 points to base*)  
  1522.        h2 := s[h1+4].i;            (*h2 points to tab*) 
  1523.        h3 := tab[h2].lev; display[h3+1] := h1;  
  1524.        h4 := s[h1+3].i + h1;
  1525.        s[h1+1].i := pc; s[h1+2].i := display[h3]; s[h1+3].i := b;
  1526.        FOR h3 := t+1 TO h4 DO s[h3].i := 0; 
  1527.        b := h1; t := h4; pc := tab[h2].adr  
  1528.      END ;  
  1529.  20: BEGIN (*index1*) h1 := ir.y;      (*h1 points to atab*)
  1530.        h2 := atab[h1].low; h3 := s[t].i;
  1531.        IF h3 < h2 THEN ps := inxchk ELSE
  1532.        IF h3 > atab[h1].high THEN ps := inxchk ELSE 
  1533.          BEGIN t := t-1; s[t].i := s[t].i + (h3-h2) 
  1534.          END
  1535.      END ;  
  1536.  21: BEGIN (*index*)  h1 := ir.y;      (*h1 points to atab*)
  1537.        h2 := atab[h1].low; h3 := s[t].i;
  1538.        IF h3 < h2 THEN ps := inxchk ELSE
  1539.        IF h3 > atab[h1].high THEN ps := inxchk ELSE 
  1540.          BEGIN t := t-1; s[t].i := s[t].i + (h3-h2)*atab[h1].elsize 
  1541.          END
  1542.      END ;  
  1543.  22: BEGIN (*load block*) h1 := s[t].i; t := t-1;
  1544.        h2 := ir.y + t; IF h2 > stacksize THEN ps := stkchk ELSE 
  1545.        WHILE t < h2 DO  
  1546.          BEGIN t := t+1; s[t] := s[h1]; h1 := h1+1  
  1547.          END
  1548.      END ;  
  1549.  23: BEGIN (*copy block*) h1 := s[t-1].i;
  1550.        h2 := s[t].i; h3 := h1 + ir.y;
  1551.        WHILE h1 < h3 DO 
  1552.          BEGIN s[h1] := s[h2]; h1 := h1+1; h2 := h2+1
  1553.          END ;  
  1554.        t := t-2 
  1555.      END ;  
  1556.  24: BEGIN (*literal*) t := t+1;
  1557.        IF t > stacksize THEN ps := stkchk ELSE s[t].i := ir.y
  1558.      END ;  
  1559.  25: BEGIN (*load real*) t := t+1;  
  1560.        IF t > stacksize THEN ps := stkchk ELSE s[t].r := rconst[ir.y]
  1561.      END ;  
  1562.  26: BEGIN (*float*) h1 := t - ir.y; s[h1].r := s[h1].i 
  1563.      END ;  
  1564.  27: BEGIN (*read*) 
  1565.        IF eof(input) THEN ps := redchk ELSE 
  1566.           CASE ir.y OF  
  1567.            1: read(s[s[t].i].i);
  1568.            2: read(s[s[t].i].r);
  1569.            4: read(s[s[t].i].c);
  1570.           END ; 
  1571.        t := t-1 
  1572.      END ;  
  1573.  28: BEGIN (*write string*) 
  1574.        h1 := s[t].i; h2 := ir.y; t := t-1;  
  1575.        chrcnt := chrcnt+h1; IF chrcnt > lineleng THEN ps := lngchk; 
  1576.        REPEAT write(stab[h2]); h1 := h1-1; h2 := h2+1
  1577.        UNTIL h1 = 0 
  1578.      END ;  
  1579.  29: BEGIN (*write1*)
  1580.        chrcnt := chrcnt + fld[ir.y];
  1581.        IF chrcnt > lineleng THEN ps := lngchk ELSE  
  1582.        CASE ir.y OF 
  1583.         1: write(s[t].i: fld[1]);
  1584.         2: write(s[t].r: fld[2]);
  1585.         3: write(s[t].b: fld[3]);
  1586.         4: write(chr(s[t].i MOD 64));
  1587.        END ;
  1588.        t := t-1 
  1589.      END ;  
  1590.  30: BEGIN (*write2*)
  1591.        chrcnt := chrcnt + s[t].i;
  1592.        IF chrcnt > lineleng THEN ps := lngchk ELSE  
  1593.        CASE ir.y OF 
  1594.         1: write(s[t-1].i: s[t].i); 
  1595.         2: write(s[t-1].r: s[t].i); 
  1596.         3: write(s[t-1].b: s[t].i); 
  1597.         4: write(chr(s[t-1].i MOD 64): s[t].i); 
  1598.        END ;
  1599.        t := t-2 
  1600.      END ;  
  1601.  31: ps := fin; 
  1602.  32: BEGIN (*exit procedure*)
  1603.        t := b-1; pc := s[b+1].i; b := s[b+3].i  
  1604.      END ;  
  1605.  33: BEGIN (*exit function*)
  1606.        t := b; pc := s[b+1].i; b := s[b+3].i
  1607.      END ;  
  1608.  34: s[t] := s[s[t].i]; 
  1609.  35: s[t].b := NOT s[t].b;  
  1610.  36: s[t].i := - s[t].i;
  1611.  37: BEGIN chrcnt := chrcnt + s[t-1].i; 
  1612.        IF chrcnt > lineleng THEN ps := lngchk ELSE  
  1613.           write(s[t-2].r: s[t-1].i: s[t].i);
  1614.        t := t-3 
  1615.      END ;  
  1616.  38: BEGIN (*store*) s[s[t-1].i] := s[t]; t := t-2  
  1617.      END ;  
  1618.  39: BEGIN t := t-1; s[t].b := s[t].r = s[t+1].r
  1619.      END ;  
  1620.  40: BEGIN t := t-1; s[t].b := s[t].r <> s[t+1].r
  1621.      END ;  
  1622.  41: BEGIN t := t-1; s[t].b := s[t].r < s[t+1].r
  1623.      END ;  
  1624.  42: BEGIN t := t-1; s[t].b := s[t].r <= s[t+1].r
  1625.      END ;  
  1626.  43: BEGIN t := t-1; s[t].b := s[t].r > s[t+1].r
  1627.      END ;  
  1628.  44: BEGIN t := t-1; s[t].b := s[t].r >= s[t+1].r
  1629.      END ;  
  1630.  45: BEGIN t := t-1; s[t].b := s[t].i = s[t+1].i
  1631.      END ;  
  1632.  46: BEGIN t := t-1; s[t].b := s[t].i <> s[t+1].i
  1633.      END ;  
  1634.  47: BEGIN t := t-1; s[t].b := s[t].i < s[t+1].i
  1635.      END ;  
  1636.  48: BEGIN t := t-1; s[t].b := s[t].i <= s[t+1].i
  1637.      END ;  
  1638.  49: BEGIN t := t-1; s[t].b := s[t].i > s[t+1].i
  1639.      END ;  
  1640.  50: BEGIN t := t-1; s[t].b := s[t].i >= s[t+1].i
  1641.      END ;  
  1642.  51: BEGIN t := t-1; s[t].b := s[t].b OR s[t+1].b
  1643.      END ;  
  1644.  52: BEGIN t := t-1; s[t].i := s[t].i + s[t+1].i
  1645.      END ;  
  1646.  53: BEGIN t := t-1; s[t].i := s[t].i - s[t+1].i
  1647.      END ;  
  1648.  54: BEGIN t := t-1; s[t].r := s[t].r + s[t+1].r;
  1649.      END ;  
  1650.  55: BEGIN t := t-1; s[t].r := s[t].r - s[t+1].r;
  1651.      END ;  
  1652.  56: BEGIN t := t-1; s[t].b := s[t].b AND s[t+1].b  
  1653.      END ;  
  1654.  57: BEGIN t := t-1; s[t].i := s[t].i * s[t+1].i
  1655.      END ;  
  1656.  58: BEGIN t := t-1;
  1657.        IF s[t+1].i = 0 THEN ps := divchk ELSE
  1658.          s[t].i := s[t].i DIV s[t+1].i  
  1659.      END ;  
  1660.  59: BEGIN t := t-1;
  1661.        IF s[t+1].i = 0 THEN ps := divchk ELSE
  1662.          s[t].i := s[t].i MOD s[t+1].i  
  1663.      END ;  
  1664.  60: BEGIN t := t-1; s[t].r := s[t].r * s[t+1].r;
  1665.      END ;  
  1666.  61: BEGIN t := t-1; s[t].r := s[t].r / s[t+1].r;
  1667.      END ;  
  1668.  62: IF eof(input) THEN ps := redchk ELSE readln;
  1669.  63: BEGIN writeln; lncnt := lncnt + 1; chrcnt := 0;
  1670.         IF lncnt > linelimit THEN ps := linchk  
  1671.      END
  1672.     END (*case*) ;  
  1673.   UNTIL ps <> run;  
  1674.  
  1675. 98: IF ps <> fin THEN
  1676.   BEGIN writeln;
  1677.     write(' halt at', pc:5, ' because of ');
  1678.     CASE ps OF  
  1679.       run:    writeln('error (see dayfile)');
  1680.       caschk: writeln('undefined case');
  1681.       divchk: writeln('division by 0'); 
  1682.       inxchk: writeln('invalid index'); 
  1683.       stkchk: writeln('storage overflow');  
  1684.       linchk: writeln('too much output');
  1685.       lngchk: writeln('line too long'); 
  1686.       redchk: writeln('reading past end of file');  
  1687.       iopr  : writeln('illegal operation'); 
  1688.       igdm  : writeln('guard mode or undefined sequence');  
  1689.       ifof  : writeln('floating point overflow');
  1690.       ifuf  : writeln('floating point underflow');  
  1691.       idof  : writeln('divide fault (div. by zero or overflow)');
  1692.       ioerr : writeln('i/o call error');
  1693.       symberr:writeln('symbiont call error');
  1694.       errcall:writeln('call on err$');  
  1695.     END ;
  1696.     h1 := b; blkcnt := 10;   (*post mortem dump*)
  1697.     REPEAT writeln; blkcnt := blkcnt - 1;
  1698.       IF blkcnt = 0 THEN h1 := 0; h2 := s[h1+4].i;  
  1699.       IF h1<>0 THEN 
  1700.         writeln(' ', tab[h2].name, ' called at', s[h1+1].i: 5); 
  1701.       h2 := btab[tab[h2].ref].last; 
  1702.       WHILE h2 <> 0 DO  
  1703.       WITH tab[h2] DO
  1704.       BEGIN IF obj = variable THEN  
  1705.             IF typ IN stantyps THEN 
  1706.             BEGIN write('    ', name, ' = ');
  1707.               IF normal THEN h3 := h1+adr ELSE h3 := s[h1+adr].i;
  1708.               CASE typ OF
  1709.                ints:  writeln(s[h3].i); 
  1710.                reals: writeln(s[h3].r); 
  1711.                bools: writeln(s[h3].b); 
  1712.                chars: writeln(chr(s[h3].i MOD 64)); 
  1713.               END
  1714.             END ;
  1715.             h2 := link  
  1716.       END ; 
  1717.       h1 := s[h1+3].i
  1718.     UNTIL h1 < 0;
  1719.   END ; 
  1720.   writeln; writeln(ocnt, ' steps')  
  1721. END (*interpret*) ; 
  1722.  
  1723. (*------------------------------------------------------------main----*)
  1724.  
  1725. BEGIN (*main*)  
  1726.    writeln('--  pascal-s   --');writeln;
  1727.    key[ 1] := 'and         '; key[ 2] := 'array       ';
  1728.    key[ 3] := 'begin       '; key[ 4] := 'case        ';
  1729.    key[ 5] := 'const       '; key[ 6] := 'div         ';
  1730.    key[ 8] := 'downto      '; key[ 7] := 'do          ';
  1731.    key[ 9] := 'else        '; key[10] := 'end         ';
  1732.    key[11] := 'for         '; key[12] := 'function    ';
  1733.    key[13] := 'if          '; key[14] := 'mod         ';
  1734.    key[15] := 'not         '; key[16] := 'of          ';
  1735.    key[17] := 'or          '; key[18] := 'procedure   ';
  1736.    key[19] := 'program     '; key[20] := 'record      ';
  1737.    key[21] := 'repeat      '; key[22] := 'then        ';
  1738.    key[23] := 'to          '; key[24] := 'type        ';
  1739.    key[25] := 'until       '; key[26] := 'var         ';
  1740.    key[27] := 'while       ';
  1741.    ksy[ 1] := andsy;        ksy[ 2] := arraysy; 
  1742.    ksy[ 3] := beginsy;      ksy[ 4] := casesy;  
  1743.    ksy[ 5] := constsy;      ksy[ 6] := idiv;
  1744.    ksy[ 8] := downtosy;     ksy[ 7] := dosy;
  1745.    ksy[ 9] := elsesy;       ksy[10] := endsy;
  1746.    ksy[11] := forsy;        ksy[12] := functionsy;  
  1747.    ksy[13] := ifsy;         ksy[14] := imod;
  1748.    ksy[15] := notsy;        ksy[16] := ofsy;
  1749.    ksy[17] := orsy;         ksy[18] := proceduresy; 
  1750.    ksy[19] := programsy;    ksy[20] := recordsy;
  1751.    ksy[21] := repeatsy;     ksy[22] := thensy;  
  1752.    ksy[23] := tosy;         ksy[24] := typesy;  
  1753.    ksy[25] := untilsy;      ksy[26] := varsy;
  1754.    ksy[27] := whilesy;  
  1755.    sps['+'] := plus;        sps['-'] := minus;  
  1756.    sps['*'] := times;       sps['/'] := rdiv;
  1757.    sps['('] := lparent;     sps[')'] := rparent;
  1758.    sps['='] := eql;         sps[','] := comma;  
  1759.    sps['['] := lbrack;      sps[']'] := rbrack; 
  1760.    sps['"'] := neq;         sps['&'] := andsy;  
  1761.    sps[';'] := semicolon;
  1762.   constbegsys := [plus,minus,intcon,realcon,charcon,ident]; 
  1763.   typebegsys := [ident,arraysy,recordsy];
  1764.   blockbegsys := [constsy,typesy,varsy,proceduresy,functionsy,beginsy]; 
  1765.   facbegsys := [intcon,realcon,charcon,ident,lparent,notsy];
  1766.   statbegsys := [beginsy,ifsy,whilesy,repeatsy,forsy,casesy];
  1767.   stantyps := [notyp,ints,reals,bools,chars];
  1768.   lc := 0; ll := 0; cc := 0; ch := ' '; 
  1769.   errpos := 0; errs := [];  
  1770.   t := -1; a := 0; b := 1; sx := 0; c2 := 0;
  1771.   display[0] := 1; reset(input); insymbol;  
  1772.   iflag := false; oflag := false; skipflag := false;
  1773.   IF sy <> programsy THEN error(3) ELSE 
  1774.  BEGIN insymbol;
  1775.     IF sy <> ident THEN error(2) ELSE
  1776.     BEGIN progname := id; insymbol; 
  1777.       IF sy <> lparent THEN error(9) ELSE
  1778.       REPEAT insymbol;  
  1779.         IF sy <> ident THEN error(2) ELSE
  1780.         BEGIN IF id = 'input       ' THEN iflag := true ELSE
  1781.               IF id = 'output      ' THEN oflag := true ELSE error(0);  
  1782.            insymbol 
  1783.         END 
  1784.       UNTIL sy <> comma;
  1785.       IF sy = rparent THEN insymbol ELSE error(4);  
  1786.       IF NOT oflag THEN error(20)
  1787.     END 
  1788.   END ; 
  1789.   enter('            ', variable, notyp, 0);  (*sentinel*)  
  1790.   enter('false       ', konstant, bools, 0);
  1791.   enter('true        ', konstant, bools, 1);
  1792.   enter('real        ', type1, reals, 1);
  1793.   enter('char        ', type1, chars, 1);
  1794.   enter('boolean     ', type1, bools, 1);
  1795.   enter('integer     ', type1, ints , 1);
  1796.   enter('abs         ', funktion, reals,0); 
  1797.   enter('sqr         ', funktion, reals,2); 
  1798.   enter('odd         ', funktion, bools,4); 
  1799.   enter('chr         ', funktion, chars,5); 
  1800.   enter('ord         ', funktion, ints, 6); 
  1801.   enter('succ        ', funktion, chars,7); 
  1802.   enter('pred        ', funktion, chars,8); 
  1803.   enter('round       ', funktion, ints, 9); 
  1804.   enter('trunc       ', funktion, ints, 10);
  1805.   enter('sin         ', funktion, reals, 11);
  1806.   enter('cos         ', funktion, reals, 12);
  1807.   enter('exp         ', funktion, reals, 13);
  1808.   enter('ln          ', funktion, reals, 14);
  1809.   enter('sqrt        ', funktion, reals, 15);
  1810.   enter('arctan      ', funktion, reals, 16);
  1811.   enter('eof         ', funktion, bools, 17);
  1812.   enter('eoln        ', funktion, bools, 18);
  1813.   enter('read        ', prozedure, notyp, 1);
  1814.   enter('readln      ', prozedure, notyp, 2);
  1815.   enter('write       ', prozedure, notyp, 3);
  1816.   enter('writeln     ', prozedure, notyp, 4);
  1817.   enter('            ', prozedure, notyp, 0);
  1818.   WITH btab[1] DO
  1819.     BEGIN last := t; lastpar := 1; psize := 0; vsize := 0
  1820.     END ;
  1821.  
  1822.   block(blockbegsys+statbegsys, false, 1);  
  1823.   IF sy <> period THEN error(22);
  1824.   emit(31);  (*halt*)
  1825.   IF btab[2].vsize > stacksize THEN error(49);  
  1826.   IF progname = 'test0       ' THEN printtables;
  1827.  
  1828.   IF errs = [] THEN 
  1829.   BEGIN 
  1830.     IF iflag THEN
  1831.       IF eof(input) THEN writeln(' input data missing')     ;
  1832.     writeln(' (eof)'); writeln; 
  1833.     interpret
  1834.   END
  1835.   ELSE errormsg;
  1836. 99: writeln 
  1837. END .
  1838.  
  1839.  
  1840.